/**
 * 
 */
package cn.ac.istic.lkt.atv;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.font.FontRenderContext;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.List;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;

/**
 * @Author shicd
 * @Date 2009-7-19
 * 
 */
public class TreePanel extends JPanel {
	/**
	 * 
	 */
	private static final long serialVersionUID = 3608874166315266650L;
	public static final Font TFONT = new Font("Serif", Font.PLAIN, 16);
	public static final Font NTFONT = new Font("Serif", Font.PLAIN, 14);
	public static final BufferedImage tempbi = new BufferedImage(200, 200, BufferedImage.TYPE_INT_ARGB);
	private final float TOPY = 30; // 和顶上的距离
	private static final float LINEHEIGHT = 30; // 两个字符的垂直举例
	private ParseTree pt;
	private List<PTNode> cs;
	//Graphics2D g2;
	//
	private float des2node; // 字符高度＋连线垂直高度
	private int nodeCount; // 字符数，不包括待分析句子的原始单词
	// private int wordCount;
	private float charHeight; // 字符高度
	private float charWidth; // 字符宽

	private String[] nodeString; // 字符
	private float[] nodeX; // 字符的位置
	private float[] nodeY; //
	private float[] nodePointX; // 两个字符间连线的位置
	private float[] nodeUpY; //
	private float[] nodeDownY;

	private final float STARTX = 30;
	private float wordSpace = 30; // 单词间的间隔
	// private String[] wordString; //句子中的单词
	// private float[] wordX;
	// private float[] wordY;
	private float[] wordPointX;
	private float[] wordPointY;

	private float maxX = 0;
	private float maxY = 0;
	private int imgWidth = 0;
	private int imgHeight = 0;

	public TreePanel() {
		super();
	}

	public TreePanel(ParseTree pt) {
		init(pt);
	}

	public void init(ParseTree pt){
		this.pt = pt;
		// paint(g2);
		maxX=0;
		maxY=0;
		imgWidth = 0;
		imgHeight = 0;
		cs = pt.getTree();
		nodeCount = cs.size();
		nodeX = new float[nodeCount];
		nodeY = new float[nodeCount];
		nodePointX = new float[nodeCount];
		nodeUpY = new float[nodeCount];
		nodeDownY = new float[nodeCount];
		wordPointX = new float[nodeCount];
		
		initNodeString();
		setBackground(Color.WHITE);

	}
	public BufferedImage paintImage(){
		
		FontRenderContext frc = tempbi.createGraphics().getFontRenderContext();
		charHeight = (float) TFONT.getMaxCharBounds(frc).getHeight();
		charWidth =((float) TFONT.getMaxCharBounds(frc).getWidth());
		des2node = charHeight + LINEHEIGHT;
		calcPos(frc );
		
		BufferedImage bi = new BufferedImage(imgWidth, imgHeight, BufferedImage.TYPE_INT_ARGB);
		Graphics2D g2 = bi.createGraphics();
		g2.setPaint(Color.black);
		myPaint(g2);
		
		/*
		JPanel panel = new JPanel();
		panel.getGraphics().drawImage(bi, 0, 0, 2000, 2000, null);
		JFrame newjf = new JFrame();
		newjf.getContentPane().add(panel);
		newjf.pack();
		newjf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		newjf.setVisible(true);
		*/


	    /*
	    try {
	    	File outputfile = new File("C:\\tmp\\img"+".png");
	    	int width = 200, height = 200;
			BufferedImage bx = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
			Graphics2D g3 = bx.createGraphics();
			g3.setPaint(Color.black);
			
		      //Font font = new Font("TimesRoman", Font.BOLD, 20);
		      //g3.setFont(font);
		      String message = "www.java2s.com!";
		      FontMetrics fontMetrics = g3.getFontMetrics();
		      int stringWidth = fontMetrics.stringWidth(message);
		      int stringHeight = fontMetrics.getAscent();
		      g3.setPaint(Color.black);
		      g3.drawString(message, (width - stringWidth) / 2, height / 2 + stringHeight / 4);

			ImageIO.write(bx, "png", outputfile);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		*/

		return bi;
	}
	
	private void myPaint(Graphics2D g2){
		g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
				RenderingHints.VALUE_ANTIALIAS_ON);
		g2.setFont(TFONT);
		FontRenderContext frc = g2.getFontRenderContext();
		charHeight = (float) TFONT.getMaxCharBounds(frc).getHeight();
		charWidth =((float) TFONT.getMaxCharBounds(frc).getWidth());
		des2node = charHeight + LINEHEIGHT;

		if (this.pt == null) {
			g2.drawString("trees", 10, 20);
			return;
		}
		calcPos(frc);
		for (int i = 0; i < nodeCount; i++) {
			if (cs.get(i).isLeafNode()){
				g2.setFont(TFONT);
			}
			else g2.setFont(NTFONT);
			//System.out.println(nodeString[i]+" "+nodeX[i]+" "+nodeY[i]);
			g2.drawString(nodeString[i], nodeX[i], nodeY[i]);
		}
		drawLines(g2,(PTNode) cs.get(0));		
	}
	public void paintComponent(Graphics g) {
		super.paintComponent(g);
		Graphics2D g2 = (Graphics2D) g;

		myPaint(g2);
		setPreferredSize(new Dimension(imgWidth,imgHeight));
		//System.err.println(maxX + this.STARTX+" "+maxY + this.STARTX);
		// updateUI();
	}
	
	public void calcPos(FontRenderContext frc ){
		// this.wordCount = getWordCount();
		setWordPointY(new float[nodeCount]);

		setWordX(frc); // 设置每一个单词的X坐标
		setNodeX(frc,0); // 设置每一个树节点的X坐标
		setTreeY(); // 设置每一个树节点的Y坐标
		imgWidth = (int)(maxX + this.STARTX);
		imgHeight = (int )(maxY + this.STARTX);
	}
	
	public Dimension getPreferredSize() {
        return new Dimension(imgWidth,imgHeight);
    }


	public void drawLines(Graphics2D g2, PTNode tn) {
		int pos = cs.indexOf(tn);
		if (tn.isLeafNode()) {
			// int p = tn.getPos();
			// Shape line = new
			// java.awt.geom.Line2D.Double(nodePointX[pos],nodeDownY[pos],wordPointX[p],wordPointY[p]);
			// g2.draw(line);
			// return;
		} else {
			int[] child = pt.getChildren(tn.getID());
			for (int i = 0; i < child.length; i++) {
				Shape line = new java.awt.geom.Line2D.Double(nodePointX[pos],
						nodeDownY[pos], nodePointX[child[i]], nodeUpY[child[i]]);
				g2.draw(line);
				PTNode t = (PTNode) this.cs.get(child[i]);
				drawLines(g2,t);
			}
		}
	}

	public void initNodeString() {
		this.nodeString = new String[this.nodeCount];
		for (int i = 0; i < nodeCount; i++) {
			PTNode tn = (PTNode) cs.get(i);
			String s = new String(tn.getLabel());
			nodeString[i] = s;
		}
	}

	/*
	 * public void getWordString(){ this.wordString = new
	 * String[this.wordCount]; for(int i=0; i<cs.size(); i++){ PTNode tn =
	 * (PTNode)cs.get(i); if(tn.isLeafNode()){ int pos = tn.getPos(); String
	 * word = tn.getLabel(); wordString[pos] = word; } } }
	 */
	public int getWordCount() {
		int wc = 0;
		for (int i = 0; i < cs.size(); i++) {
			PTNode tn = (PTNode) cs.get(i);
			if (tn.isLeafNode())
				wc++;
		}
		return wc;
	}

	public void setWordX(FontRenderContext frc ) { // leafnode x pos
		float xpos = this.STARTX;
		for (int i = 0; i < this.cs.size(); i++) {
			PTNode nd = cs.get(i);
			if (nd.isLeafNode()) {
				nodeX[i] = xpos;
				float stringwidth = (float) TFONT.getStringBounds(
						nd.getLabel(), frc).getWidth();
				setWordPointX(i, xpos, stringwidth);
				xpos = xpos + stringwidth + this.wordSpace; // 下一个词的位置为当前词的位置＋当前词的宽度＋词间空格的宽度
				if (this.maxX < xpos) {
					this.maxX = xpos;
				}
			}
			// System.out.println(nodeX[i]);
		}
	}

	public void setWordPointX(int pos, float baseX, float sw) {
		this.wordPointX[pos] = baseX + sw / 2;
	}

	public float setNodeX(FontRenderContext frc , int index) {
		PTNode tn = (PTNode) this.cs.get(index);
		if (tn.isLeafNode()) {

			// int pos = tn.getPos();
			this.nodePointX[index] = this.wordPointX[index]; // node string的中间
			// this.nodeX[index]=this.wordX[index];
			// float strWidth =
			// (float)DFONT.getStringBounds(this.nodeString[index],this.frc).getWidth();
			// this.nodeX[index]= this.nodePointX[index]-strWidth/2; //node
			// string的开始
			// System.out.print(this.nodePointX[index]);
			return this.nodePointX[index];

			// return -1;
		} else {
			int[] child = pt.getChildren(tn.getID());
			float sum = 0;
			for (int i = 0; i < child.length; i++) {
				sum = sum + setNodeX( frc ,child[i]);
			}
			this.nodePointX[index] = sum / child.length;
			float strWidth = (float) TFONT.getStringBounds(tn.getLabel(),
					frc).getWidth();
			this.nodeX[index] = this.nodePointX[index] - strWidth / 2;
			return this.nodePointX[index];
		}
	}

	public void setTreeY() {
		int treeDep = pt.getDepth();
		// System.out.println("tree depth:"+treeDep);
		int nodeDep;
		// 所有的node
		for (int i = 0; i < this.nodeCount; i++) {
			nodeDep = cs.get(i).getHeight();
			// System.out.println("tree node "+i+" depth:"+nodeDep);
			this.nodeY[i] = this.TOPY + (treeDep - nodeDep) * des2node;
			// this.nodeY[i] = this.TOPY+nodeDep*des2node;
			this.nodeDownY[i] = this.nodeY[i] + this.charHeight / 5;
			this.nodeUpY[i] = this.nodeY[i] - this.charHeight / 3 * 2;
			PTNode tn = (PTNode) this.cs.get(i);
			if (tn.isLeafNode()) {
				this.nodeY[i] = this.nodeY[i];// +des2node;
				// this.wordPointY[i] = this.nodeY[i];//-this.charHeight/3*2;
				this.maxY = this.nodeY[i];

			}
		}
	}

	public void saveImage() {

		BufferedImage bi = (BufferedImage) this.createImage(this
				.getPreferredSize().width, this.getPreferredSize().height);
		paint(bi.getGraphics());
		try {
			File directory = new File(".");
			javax.imageio.ImageIO.write(bi, "bmp", new File(directory
					.getCanonicalPath()
					+ "/gant.bmp"));
		} catch (IOException e1) {
			// TODO 自动生成 catch 块
			e1.printStackTrace();
		}
	}


	public float getCharWidth() {
		return charWidth;
	}

	public void setWordPointY(float[] wordPointY) {
		this.wordPointY = wordPointY;
	}

	public float[] getWordPointY() {
		return wordPointY;
	}

	public ParseTree getPt() {
		return pt;
	}

	public void setPt(ParseTree pt) {
		this.pt = pt;
	}

	public int getImgWidth() {
		return imgWidth;
	}

	public void setImgWidth(int imgWidth) {
		this.imgWidth = imgWidth;
	}

	public int getImgHeight() {
		return imgHeight;
	}

	public void setImgHeight(int imgHeight) {
		this.imgHeight = imgHeight;
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		ParseTree pt = new ParseTree(
				"( (IP-HLN (NP-SBJ (NP-PN (NR 上海) (NR 浦东))  (NP (NN 开发) (CC 与) (NN 法制) (NN 建设))) (VP (VV 同步))) ) ");
		// pt.Parse();

		TreePanel csp = new TreePanel(pt);
		JFrame jf = new JFrame();
		JScrollPane scrollpane = new JScrollPane(csp);
		// scrollpane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
		// scrollpane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);

		jf.getContentPane().add(scrollpane);
		jf.pack();
		jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		jf.setVisible(true);
		// csp.saveImage();
	}
}
